{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "35227754",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<!-- \n",
       "If you can see this code, this cell's output is not trusted.\n",
       "Please execute this cell and save the notebook, or click File -> Trust Notebook\n",
       "-->\n",
       "<script>\n",
       "var shown = true;\n",
       "\n",
       "function filter_cells_by_tag(tag) {\n",
       "    out = Array();\n",
       "    all_cells = Jupyter.notebook.get_cells()\n",
       "    for (var i=0; i<all_cells.length; i++) {\n",
       "        var curr_cell = all_cells[i];\n",
       "        var tags = curr_cell._metadata.tags;\n",
       "        if (tags != undefined) {\n",
       "            for (var j=0; j<tags.length; j++) {\n",
       "                var curr_tag = tags[j];\n",
       "                if (curr_tag == tag) {\n",
       "                    out.push(curr_cell);\n",
       "                    break;\n",
       "                }\n",
       "            }\n",
       "        }\n",
       "    }\n",
       "    return out;\n",
       "}\n",
       "\n",
       "function set_cell_visibility(tag, show, input_only) {\n",
       "    var cells = Jupyter.notebook.get_cells();\n",
       "    var marked_cells = filter_cells_by_tag(tag);\n",
       "    for (var i=0; i<marked_cells.length; i++) {\n",
       "        var curr_cell = marked_cells[i];\n",
       "        if (input_only) {\n",
       "            obj = curr_cell.input\n",
       "        } else {\n",
       "            obj = curr_cell.element\n",
       "        }\n",
       "        if (show) {\n",
       "            obj.show();\n",
       "        } else {\n",
       "            obj.hide();\n",
       "        }\n",
       "    }\n",
       "}\n",
       "\n",
       "function toggle_cell_visibility(tag) {\n",
       "    set_cell_visibility(tag, shown, false)\n",
       "    shown = ! shown;\n",
       "}\n",
       "\n",
       "set_cell_visibility('execution_cell', false, true);\n",
       "</script>\n",
       "To toggle visibility of explanation cells click <a href=\"javascript:toggle_cell_visibility('explanatory_cell')\">here</a>\n"
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%%html\n",
    "<!-- \n",
    "If you can see this code, this cell's output is not trusted.\n",
    "Please execute this cell and save the notebook, or click File -> Trust Notebook\n",
    "-->\n",
    "<script>\n",
    "var shown = true;\n",
    "\n",
    "function filter_cells_by_tag(tag) {\n",
    "    out = Array();\n",
    "    all_cells = Jupyter.notebook.get_cells()\n",
    "    for (var i=0; i<all_cells.length; i++) {\n",
    "        var curr_cell = all_cells[i];\n",
    "        var tags = curr_cell._metadata.tags;\n",
    "        if (tags != undefined) {\n",
    "            for (var j=0; j<tags.length; j++) {\n",
    "                var curr_tag = tags[j];\n",
    "                if (curr_tag == tag) {\n",
    "                    out.push(curr_cell);\n",
    "                    break;\n",
    "                }\n",
    "            }\n",
    "        }\n",
    "    }\n",
    "    return out;\n",
    "}\n",
    "\n",
    "function set_cell_visibility(tag, show, input_only) {\n",
    "    var cells = Jupyter.notebook.get_cells();\n",
    "    var marked_cells = filter_cells_by_tag(tag);\n",
    "    for (var i=0; i<marked_cells.length; i++) {\n",
    "        var curr_cell = marked_cells[i];\n",
    "        if (input_only) {\n",
    "            obj = curr_cell.input\n",
    "        } else {\n",
    "            obj = curr_cell.element\n",
    "        }\n",
    "        if (show) {\n",
    "            obj.show();\n",
    "        } else {\n",
    "            obj.hide();\n",
    "        }\n",
    "    }\n",
    "}\n",
    "\n",
    "function toggle_cell_visibility(tag) {\n",
    "    set_cell_visibility(tag, shown, false)\n",
    "    shown = ! shown;\n",
    "}\n",
    "\n",
    "set_cell_visibility('execution_cell', false, true);\n",
    "</script>\n",
    "To toggle visibility of explanation cells click <a href=\"javascript:toggle_cell_visibility('explanatory_cell')\">here</a>\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e908195c",
   "metadata": {},
   "source": [
    "# Email Preprocessing"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "727614ba",
   "metadata": {},
   "source": [
    "This notebook defines the steps for extracting the different components (header, body, attachments, etc.) of an email (`.eml` file). To see how to create a generalized API for all documents see `pipeline-general` directory.\n",
    "\n",
    "To demonstrate how off-the-shelf Unstructured Bricks extract meaningful data from complex source documents, we will apply a series of Bricks with explanations.\n",
    "\n",
    "#### Table of Contents\n",
    "\n",
    "1. [Take a Look at a Raw EML File](#explore)\n",
    "1. [Custom Partitioning Bricks](#custom)\n",
    "1. [Cleaning Bricks](#cleaning)\n",
    "1. [Staging Bricks](#staging)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3848e558",
   "metadata": {},
   "source": [
    "## Section 1: Take a Look at a Raw EML File <a id=\"explore\"></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "01a62fe4",
   "metadata": {},
   "source": [
    "Let's take a look at an email with an attachment. As you will see below there is metadata about the email at the top (sender, recipient, subject, etc.) and if you scroll down, you will will see there are different sections of the email and it's metadata. There is one part `X-MS-Has-Attach: yes` which indicates this email has an attachment. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "71814e12",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "import json\n",
    "\n",
    "\n",
    "def get_filename(directory, filename):\n",
    "    cwd = os.getcwd()\n",
    "    local_directory = os.path.join(os.path.split(cwd)[0], directory)\n",
    "    ci_directory = os.path.join(cwd, directory)\n",
    "\n",
    "    if os.path.exists(local_directory) and filename in os.listdir(local_directory):\n",
    "        return os.path.join(local_directory, filename)\n",
    "    elif os.path.exists(ci_directory) and filename in os.listdir(ci_directory):\n",
    "        return os.path.join(ci_directory, filename)\n",
    "    else:\n",
    "        raise FileNotFoundError"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "72f0ebc4",
   "metadata": {},
   "outputs": [],
   "source": [
    "filename = get_filename(\"sample-docs\", \"fake-email-attachment.eml\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ff34cce7",
   "metadata": {},
   "outputs": [],
   "source": [
    "import email\n",
    "\n",
    "with open(filename) as f:\n",
    "    msg = email.message_from_file(f)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "63e3b32b",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9925f0bf",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "MIME-Version: 1.0\n",
      "Date: Fri, 23 Dec 2022 12:08:48 -0600\n",
      "Message-ID: <CAPgNNXSzLVJ-d1OCX_TjFgJU7ugtQrjFybPtAMmmYZzphxNFYg@mail.gmail.com>\n",
      "Subject: Fake email with attachment\n",
      "From: Mallori Harrell <mallori@unstructured.io>\n",
      "To: Mallori Harrell <mallori@unstructured.io>\n",
      "Content-Type: multipart/mixed; boundary=\"0000000000005d654405f082adb7\"\n",
      "\n",
      "--0000000000005d654405f082adb7\n",
      "Content-Type: multipart/alternative; boundary=\"0000000000005d654205f082adb5\"\n",
      "\n",
      "--0000000000005d654205f082adb5\n",
      "Content-Type: text/plain; charset=\"UTF-8\"\n",
      "\n",
      "Hello!\n",
      "\n",
      "Here's the attachments!\n",
      "\n",
      "It includes:\n",
      "\n",
      "   - Lots of whitespace\n",
      "   - Little to no content\n",
      "   - and is a quick read\n",
      "\n",
      "Best,\n",
      "\n",
      "Mallori\n",
      "\n",
      "--0000000000005d654205f082adb5\n",
      "Content-Type: text/html; charset=\"UTF-8\"\n",
      "Content-Transfer-Encoding: quoted-printable\n",
      "\n",
      "<div dir=3D\"ltr\">Hello!=C2=A0<div><br></div><div>Here&#39;s the attachments=\n",
      "!</div><div><br></div><div>It includes:</div><div><ul><li style=3D\"margin-l=\n",
      "eft:15px\">Lots of whitespace</li><li style=3D\"margin-left:15px\">Little=C2=\n",
      "=A0to no content</li><li style=3D\"margin-left:15px\">and is a quick read</li=\n",
      "></ul><div>Best,</div></div><div><br></div><div>Mallori</div><div dir=3D\"lt=\n",
      "r\" class=3D\"gmail_signature\" data-smartmail=3D\"gmail_signature\"><div dir=3D=\n",
      "\"ltr\"><div><div><br></div></div></div></div></div>\n",
      "\n",
      "--0000000000005d654205f082adb5--\n",
      "\n",
      "--0000000000005d654405f082adb7\n",
      "Content-Type: text/plain; charset=\"US-ASCII\"; name=\"fake-attachment.txt\"\n",
      "Content-Disposition: attachment; filename=\"fake-attachment.txt\"\n",
      "Content-Transfer-Encoding: base64\n",
      "X-Attachment-Id: f_lc0tto5j0\n",
      "Content-ID: <f_lc0tto5j0>\n",
      "\n",
      "SGV5IHRoaXMgaXMgYSBmYWtlIGF0dGFjaG1lbnQh\n",
      "--0000000000005d654405f082adb7--\n",
      "\n",
      "Content-Type: multipart/alternative; boundary=\"0000000000005d654205f082adb5\"\n",
      "\n",
      "--0000000000005d654205f082adb5\n",
      "Content-Type: text/plain; charset=\"UTF-8\"\n",
      "\n",
      "Hello!\n",
      "\n",
      "Here's the attachments!\n",
      "\n",
      "It includes:\n",
      "\n",
      "   - Lots of whitespace\n",
      "   - Little to no content\n",
      "   - and is a quick read\n",
      "\n",
      "Best,\n",
      "\n",
      "Mallori\n",
      "\n",
      "--0000000000005d654205f082adb5\n",
      "Content-Type: text/html; charset=\"UTF-8\"\n",
      "Content-Transfer-Encoding: quoted-printable\n",
      "\n",
      "<div dir=3D\"ltr\">Hello!=C2=A0<div><br></div><div>Here&#39;s the attachments=\n",
      "!</div><div><br></div><div>It includes:</div><div><ul><li style=3D\"margin-l=\n",
      "eft:15px\">Lots of whitespace</li><li style=3D\"margin-left:15px\">Little=C2=\n",
      "=A0to no content</li><li style=3D\"margin-left:15px\">and is a quick read</li=\n",
      "></ul><div>Best,</div></div><div><br></div><div>Mallori</div><div dir=3D\"lt=\n",
      "r\" class=3D\"gmail_signature\" data-smartmail=3D\"gmail_signature\"><div dir=3D=\n",
      "\"ltr\"><div><div><br></div></div></div></div></div>\n",
      "\n",
      "--0000000000005d654205f082adb5--\n",
      "\n",
      "Content-Type: text/plain; charset=\"UTF-8\"\n",
      "\n",
      "Hello!\n",
      "\n",
      "Here's the attachments!\n",
      "\n",
      "It includes:\n",
      "\n",
      "   - Lots of whitespace\n",
      "   - Little to no content\n",
      "   - and is a quick read\n",
      "\n",
      "Best,\n",
      "\n",
      "Mallori\n",
      "\n",
      "Content-Type: text/html; charset=\"UTF-8\"\n",
      "Content-Transfer-Encoding: quoted-printable\n",
      "\n",
      "<div dir=3D\"ltr\">Hello!=C2=A0<div><br></div><div>Here&#39;s the attachments=\n",
      "!</div><div><br></div><div>It includes:</div><div><ul><li style=3D\"margin-l=\n",
      "eft:15px\">Lots of whitespace</li><li style=3D\"margin-left:15px\">Little=C2=\n",
      "=A0to no content</li><li style=3D\"margin-left:15px\">and is a quick read</li=\n",
      "></ul><div>Best,</div></div><div><br></div><div>Mallori</div><div dir=3D\"lt=\n",
      "r\" class=3D\"gmail_signature\" data-smartmail=3D\"gmail_signature\"><div dir=3D=\n",
      "\"ltr\"><div><div><br></div></div></div></div></div>\n",
      "\n",
      "Content-Type: text/plain; charset=\"US-ASCII\"; name=\"fake-attachment.txt\"\n",
      "Content-Disposition: attachment; filename=\"fake-attachment.txt\"\n",
      "Content-Transfer-Encoding: base64\n",
      "X-Attachment-Id: f_lc0tto5j0\n",
      "Content-ID: <f_lc0tto5j0>\n",
      "\n",
      "SGV5IHRoaXMgaXMgYSBmYWtlIGF0dGFjaG1lbnQh\n"
     ]
    }
   ],
   "source": [
    "# Take a look at the eml file with all the metadata and content\n",
    "for part in msg.walk():\n",
    "    print(part)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5769a88f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "('MIME-Version', '1.0')\n",
      "('Date', 'Fri, 23 Dec 2022 12:08:48 -0600')\n",
      "('Message-ID', '<CAPgNNXSzLVJ-d1OCX_TjFgJU7ugtQrjFybPtAMmmYZzphxNFYg@mail.gmail.com>')\n",
      "('Subject', 'Fake email with attachment')\n",
      "('From', 'Mallori Harrell <mallori@unstructured.io>')\n",
      "('To', 'Mallori Harrell <mallori@unstructured.io>')\n",
      "('Content-Type', 'multipart/mixed; boundary=\"0000000000005d654405f082adb7\"')\n"
     ]
    }
   ],
   "source": [
    "# Take a closer look at the header section of the eml file\n",
    "for part in msg.raw_items():\n",
    "    print(part)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "15d69b6b",
   "metadata": {},
   "source": [
    "## Section 2: Custom Partition Bricks"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "5c9e618c",
   "metadata": {},
   "source": [
    "Let's take a look at the body text of the eml file."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "11573046",
   "metadata": {},
   "outputs": [],
   "source": [
    "from unstructured.partition.email import partition_email\n",
    "\n",
    "elements = partition_email(filename=filename)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ab65b4e5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<unstructured.documents.html.HTMLTitle>,\n",
       " <unstructured.documents.html.HTMLNarrativeText>,\n",
       " <unstructured.documents.html.HTMLNarrativeText>,\n",
       " <unstructured.documents.html.HTMLListItem>,\n",
       " <unstructured.documents.html.HTMLListItem>,\n",
       " <unstructured.documents.html.HTMLListItem>,\n",
       " <unstructured.documents.html.HTMLText>,\n",
       " <unstructured.documents.html.HTMLTitle>]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "elements"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ed070893",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello! \n",
      "Here's the attachments!\n",
      "It includes:\n",
      "Lots of whitespace\n",
      "Little to no content\n",
      "and is a quick read\n",
      "Best,\n",
      "Mallori\n"
     ]
    }
   ],
   "source": [
    "print(elements[0].text)\n",
    "print(elements[1].text)\n",
    "print(elements[2].text)\n",
    "print(elements[3].text)\n",
    "print(elements[4].text)\n",
    "print(elements[5].text)\n",
    "print(elements[6].text)\n",
    "print(elements[7].text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5eefd575",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello! \n",
      "Here's the attachments!\n",
      "It includes:\n",
      "Lots of whitespace\n",
      "Little to no content\n",
      "and is a quick read\n",
      "Best,\n",
      "Mallori\n"
     ]
    }
   ],
   "source": [
    "for element in elements:\n",
    "    print(element)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "258531fe",
   "metadata": {},
   "source": [
    "We can use the same code with extra parameters to also extract the header of the eml file"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9eca4b0f",
   "metadata": {},
   "outputs": [],
   "source": [
    "elements_with_header = partition_email(filename=filename, include_headers=True)"
   ]
  },
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "9c77f127",
   "metadata": {},
   "source": [
    "Let's also extract the attachment from the eml file. We can extract the file's metadata and payload. You can save the attachment to your local drive by specifying a directory for the `output_dir` paramenter."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "42fd5970",
   "metadata": {},
   "outputs": [],
   "source": [
    "from unstructured.partition.email import extract_attachment_info\n",
    "with open(filename) as f:\n",
    "    msg = email.message_from_file(f)\n",
    "    \n",
    "attachments = extract_attachment_info(msg)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a9d6e28e",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'filename': 'fake-attachment.txt',\n",
       "  'payload': b'Hey this is a fake attachment!'}]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "attachments"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "10e1d3df",
   "metadata": {},
   "source": [
    "## Section 3: Cleaning Bricks <a id=\"cleaning\"></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "52943c00",
   "metadata": {},
   "source": [
    "In addition to partitioning bricks, the Unstructured library has\n",
    "***cleaning*** bricks for removing unwanted content from text. In this\n",
    "case, we'll solve our whitespace problem by using the \n",
    "`clean_extra_whitespace`. Other uses for cleaning bricks include\n",
    "cleaning out boilerplate, sentence fragments, and other segments\n",
    "of text that could impact labeling tasks or the accuracy of\n",
    "machine learning models. As with partitioning bricks, users can\n",
    "include custom cleaning bricks in a pipeline."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "268e7dcd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Hello!\\xa0'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#This element has a lot of new line characters\n",
    "elements[0].text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "485198a5",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Hello!'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from functools import partial\n",
    "from unstructured.cleaners.core import clean_extra_whitespace, remove_punctuation\n",
    "\n",
    "clean_extra_whitespace(elements[0].text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1639d006",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'It includes:'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "elements[2].text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "496281c1",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'It includes'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "remove_punctuation(elements[2].text)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "da79cb9c",
   "metadata": {},
   "outputs": [],
   "source": [
    "clean_elements = []\n",
    "cleaners = [clean_extra_whitespace, remove_punctuation]\n",
    "for element in elements:\n",
    "    element.apply(*cleaners)\n",
    "    clean_elements.append(element)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0f7fea99",
   "metadata": {},
   "source": [
    "## Section 4: Staging Bricks<a id=\"staging\"></a>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "97d2bd5c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Hello'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "clean_elements[0].text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a4cb2037",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'It includes'"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "clean_elements[2].text"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4f41f82c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'data': {'text': 'Hello', 'ref_id': '924fccbb252c7027c692cab39aa9c952'}},\n",
       " {'data': {'text': 'Heres the attachments',\n",
       "   'ref_id': 'cfa6629abfb0222b3b4b89ed9333280a'}},\n",
       " {'data': {'text': 'It includes',\n",
       "   'ref_id': '3fe3ec352ef9c8089ee5feb6ddf8d324'}},\n",
       " {'data': {'text': 'Lots of whitespace',\n",
       "   'ref_id': '0cd12c1692d24b6ceaed1baaf82d6186'}},\n",
       " {'data': {'text': 'Little to no content',\n",
       "   'ref_id': 'b11ebd7a352bca2b850f79cb100591de'}},\n",
       " {'data': {'text': 'and is a quick read',\n",
       "   'ref_id': '1f4fcaa93cbb457d397235afcb380953'}},\n",
       " {'data': {'text': 'Best', 'ref_id': 'b69770ef35263fe11a6796b022b66698'}},\n",
       " {'data': {'text': 'Mallori', 'ref_id': 'b594cbd758a427db6c4a4a967e893e23'}}]"
      ]
     },
     "execution_count": null,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from unstructured.staging.label_studio import stage_for_label_studio\n",
    "\n",
    "label_studio_data = stage_for_label_studio(clean_elements)\n",
    "label_studio_data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "63dc5217",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "python3",
   "language": "python",
   "name": "python3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
